﻿using BJoin.DapperExtension.DatabaseFactory;
using DapperExtensions;
using DapperExtensions.Sql;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

namespace BJoin.DapperExtension.Postgresql
{
    public static class Extension
    {
        /// <summary>
        /// 使用IDatabase用法
        /// </summary>
        /// <param name="services"></param>
        /// <param name="SqlDialect"></param>
        /// <param name="CreateConnection"></param>
        /// <param name="UseExtension">是否同时使用扩展方法</param>
        /// <returns></returns>
        public static IServiceCollection AddDapperPostgresql(this IServiceCollection services, Func<IDbConnection> CreateConnection, bool UseExtension = false, Type defaultMapper = null, IList<Assembly> mappingAssemblies = null)
        {
            var SqlDialect = SqlDialectUtil.ConvertESqlDialect(ESqlDialect.PostgreSql);
            services.AddOptions();
            services.Configure<DataBaseOptions>(opt =>
            {
                opt.DbConnection = CreateConnection;
                opt.SqlDialect = SqlDialectUtil.ConvertESqlDialect(ESqlDialect.PostgreSql);
            });

            if (UseExtension)
            {
                var Configuration = new DapperExtensionsConfiguration(defaultMapper, mappingAssemblies, SqlDialect);

#pragma warning disable S125 // Sections of code should not be commented out
                //DapperExtensions.Configure(Configuration);
#pragma warning restore S125 // Sections of code should not be commented out
                services.AddSingleton<IDapperExtensionsConfiguration>(Configuration);
            }
            else
                services.AddSingleton<IDapperExtensionsConfiguration, DapperExtensionsConfiguration>();
            services.AddSingleton<ISqlGenerator, SqlGeneratorImpl>();
            services.AddSingleton<IDapperImplementor, PostgresqlImplement>();
            services.AddScoped<IDatabase, Database>();
            return services;
        }
        /// <summary>
        /// 使用IDbFactory用法
        /// </summary>
        /// <param name="services"></param>
        /// <param name="setupOpt"></param>
        /// <param name="defaultMapper"></param>
        /// <param name="mappingAssemblies"></param>
        /// <returns></returns>
        public static IServiceCollection AddDapperPostgresql(this IServiceCollection services, Action<DbFactoryOptions> setupOpt, Type defaultMapper = null, IList<Assembly> mappingAssemblies = null)
        {
            var SqlDialect = SqlDialectUtil.ConvertESqlDialect(ESqlDialect.PostgreSql);
            services.AddOptions();
            services.Configure(setupOpt);

            var Configuration = new DapperExtensionsConfiguration(defaultMapper, mappingAssemblies, SqlDialect);
            services.AddSingleton<IDapperExtensionsConfiguration>(Configuration);

            services.AddSingleton<ISqlGenerator, SqlGeneratorImpl>();
            services.AddSingleton<IDapperImplementor, PostgresqlImplement>();
            services.AddSingleton<Func<IDbConnection, IDatabase>>(sp =>
            {
                var dapperConfig = sp.GetRequiredService<IDapperExtensionsConfiguration>();
                var sqlImplement = sp.GetRequiredService<IDapperImplementor>();
                return c => new Database(c, new SqlGeneratorImpl(dapperConfig), sqlImplement);
            });
            services.AddSingleton<IReadConnectionSelector, ReadConnectionSelector>();
            services.AddSingleton<IDbFactory<IDatabase, long?>, DatabaseFactory.DatabaseFactory>();
            return services;
        }
    }
}
